#!/bin/bash
# 需使用环境变量PBC_RUNNER指定d8路径
# 使用方式：./test_pbc.sh [-d <目标pbc文件夹路径> | -i <目标pbc文件路径> ] [--extra-flags "<额外参数>"] [--timeout <超时时间(秒)>]
# 配置默认值
extra_flags=""
directory="hermes-tests"
input_files=()
timeout_seconds=30

# 解析命令行参数
parse_args() {
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --extra-flags)
                extra_flags="$2"
                shift 2
                ;;
            -i|--input)
                shift
                while [[ $# -gt 0 && ! "$1" =~ ^- ]]; do
                    input_files+=("$1")
                    shift
                done
                ;;
            -d|--directory)
                directory="$2"
                shift 2
                ;;
            --timeout)
                timeout_seconds="$2"
                if ! [[ "$timeout_seconds" =~ ^[1-9][0-9]*$ ]]; then
                    echo "错误: 超时时间必须是正整数"
                    exit 1
                fi
                shift 2
                ;;
            *)
                echo "未知参数: $1"
                exit 1
                ;;
        esac
    done
}

get_pbc_files() {
    local path="$1"
    find "$path" -type f -name "*.pbc" | while read -r file; do
        realpath --relative-to="$path" "$file"
    done
}

run_d8() {
    local file="$1"
    echo "--- Run test start: $file"
    
    # 使用环境变量PBC_RUNNER指定d8路径
    if [[ -z "$PBC_RUNNER" ]]; then
        echo "错误: 请通过export PBC_RUNNER=指定d8可执行文件路径"
        return 1
    fi
    d8_path="$PBC_RUNNER"
    
    if [[ ! -x "$d8_path" ]]; then
        echo "错误: d8可执行文件不存在于指定路径 $d8_path"
        return 1
    fi

    if [[ ! -f "$file" ]]; then
        echo "错误: pbc文件不存在 - $file"
        return 1
    fi

    local command_base="$d8_path --expose-gc --use-pbc $extra_flags"
    local full_command="$command_base $file"
    
    local base_name="${file%.pbc}"
    local real_output="${base_name}-real.txt"
    local expected_result="${base_name}-result.txt"
    
    rm -f "$real_output"
    
    timeout "$timeout_seconds"s $full_command > "$real_output" 2>&1
    
    local ret=$?
    
    if [[ $ret -eq 124 ]]; then
        echo "--- Run test ERROR: 执行超时 (超过${timeout_seconds}秒)"
        return 1
    elif [[ $ret -ne 0 ]]; then
        echo "--- Run test ERROR: 执行命令返回非零状态码 $ret"
        return 1
    fi
    
    if [[ -f "$expected_result" ]]; then
        local count=$(wc -l < "$expected_result")
        diff <(tail -n "$count" "$real_output") <(tail -n "$count" "$expected_result")
        ret=$?
        if [[ $ret -ne 0 ]]; then
            echo "--- Run test ERROR: 结果与预期不符"
            return 1
        fi
    fi
    
    echo "--- Run test   end: $file SUCCESS ---"
    return 0
}

main() {
    parse_args "$@"

    local files=()
    local tests_path=""
    
    if [[ ${#input_files[@]} -gt 0 ]]; then
        files=("${input_files[@]}")
        tests_path=""
    else
        tests_path="$directory/"
        files=($(get_pbc_files "$directory"))
    fi
    
    for file in "${files[@]}"; do
        if [[ "$file" != *.pbc ]]; then
            echo "错误: $file 不是有效的.pbc文件"
            exit 1
        fi
    done
    
    if [[ ${#files[@]} -eq 1 ]]; then
        local test_file="${tests_path}${files[0]}"
        if run_d8 "$test_file"; then
            echo "Test ok."
            exit 0
        else
            echo "Test error!"
            exit 1
        fi
    fi
    
    local error_list=()
    
    for file in "${files[@]}"; do
        local real_path="${tests_path}${file}"
        if ! run_d8 "$real_path"; then
            error_list+=("$real_path")
        fi
    done
    
    all_cases=()
    for file in "${files[@]}"; do
        all_cases+=("${tests_path}${file}")
    done
    
    local success_list="pbc_success_list.txt"
    > "$success_list"
    for case in "${all_cases[@]}"; do
        if ! [[ " ${error_list[@]} " =~ " $case " ]]; then
            echo "$case" >> "$success_list"
        fi
    done
    sort -i "$success_list" -o "$success_list"

    echo "总测试用例数: ${#all_cases[@]}"
    echo "成功: $(( ${#all_cases[@]} - ${#error_list[@]} ))"
    echo "失败: ${#error_list[@]}"
    
    if [[ ${#error_list[@]} -eq 0 ]]; then
        echo "All Test Case PASS"
        for file in "${files[@]}"; do
            local base_name="${tests_path}${file%.pbc}"
            rm -f "${base_name}.jsc"
            rm -f "${base_name}-real.txt"
            rm -f "${base_name}.hbc"
        done
        exit 0
    else
        echo "失败的测试用例列表:"
        printf "%s\n" "${error_list[@]}"
        exit 1
    fi
}

main "$@"